# -*- coding: utf-8 -*-
class Extensions::AirController < ApplicationController

  before_filter :user_authorize, :except => [:login]

  @is_logined = false


  ###########################################################
  # メソッド：air_loginアクション
  # 概　　要：Airアプリからのログイン処理
  ###########################################################
  def login
    case request.method
      when :post
        if user = MstUser.authenticate(params['user_login_id'], params['user_password'])
          #ログイン日時更新
          user.update_attribute(:last_login_on, Time.now)
          item_list = {}
          #item_list[:user_login_id] = params['user_login_id']
          #item_list[:user_password] = params['user_password']
          item_list[:user_login_id] = user.login_id
          item_list[:user_password] = user.password
          item_list[:id] = user.id
          result = {
            :items => item_list
          }
          render :text => result_for_json( true, '', result )
      return
        else
          result = {
            :items => ""
          }
          render :text => result_for_json( false, '', result )
          return
      end
      result = {
        :items => ""
      }
      render :text => result_for_json( false, '', result )
      return
    else
      render :text => 'access denied!'
    end
  end


  #
  #--
  #Airアプリにより呼び出される各データの初期化データ
  #++
  #

  #
  #=== json_init_usersアクション
  #
  #認証されたユーザが所属するプロジェクトに関連するユーザ情報を返却する
  #
  def json_init_users
    users    = []
    user_ids = []
    projectusers = my_projects_users
    projectusers.each do |u|
      attr = u.mst_user.attributes
      attr.delete('srcpassword')
      attr['password'] = nil unless u.mst_user.id == @current_user.id
      unless user_ids.include? u.mst_user.id
        user_ids << u.mst_user.id
        users << attr
      end
    end
    #attre
    result = {:items => users}
    render :text => result_for_json(true, '', result)
  end

  ###########################################################
  # メソッド：json_init_projectsアクション
  # 概　　要：dat_projects情報をJSON形式で返す。
  #           Airアプリから呼び出される
  ###########################################################
  def json_init_projects
    projects = my_projects
    item_list = []
    projects.each do |project|
         item_list.push(project.attributes)
    end
    result = {
      :items => item_list
    }
    render :text => result_for_json(true, '', result)
  end


  ###########################################################
  # メソッド：json_init_project_usersアクション
  # 概　　要：dat_project_users情報をJSON形式で返す。
  #           Airアプリから呼び出される
  ###########################################################
  def json_init_project_users
    users = []
    projects = my_projects
    projects.each do |p|
      projectusers = p.dat_projectusers.find(:all, :include => :mst_user)
      projectusers.each do |u|
        attr = u.attributes
        attr.delete(:src_password)
        users << attr
      end
    end
    result = {:items => users}
    render :text => result_for_json(true, '', result)
  end




  ###########################################################
  # メソッド：json_init_project_compsアクション
  # 概　　要：dat_project_comps情報をJSON形式で返す。
  #           Airアプリから呼び出される
  ###########################################################
  def json_init_project_comps
    item_list = []
    projects = my_projects_for_includes()
    projects.each do | project |
      items = project.dat_projectcomps.map do |pc|
        {
          :id                    => pc.id,
          :project_id            => pc.project_id,
          :line_no               => pc.line_no,
          :task_kbn              => pc.task_kbn,
            :item_name           => pc.item_name,
            :item_name           => pc.item_name,
            :class_word1         => pc.class_word1,
            :class_word2         => pc.class_word2,
            :class_word3         => pc.class_word3,
            :create_user_id      => pc.create_user_id,
            :created_on          => pc.created_on,
            :update_user_id      => pc.update_user_id,
            :updated_on          => pc.updated_on,
            :last_operation_kbn  => pc.last_operation_kbn
        }
      end
      item_list.concat items
    end
    result = {
      :items => item_list
    }
    render :text => result_for_json(true, '', result)
  end



  ###########################################################
  # メソッド：json_init_project_logsアクション
  # 概　　要：dat_projectlogs情報をJSON形式で返す。
  #           Airアプリから呼び出される
  ###########################################################
  def json_init_project_logs
    item_list = []
    projects = my_projects_for_includes()
    projects.each do | project |
      project.dat_projectcomps.each do |pc|
        items = pc.dat_projectlogs.map do |pl|
          {
            :id             => pl.id,
            :projectcomp_id => pl.projectcomp_id,
            :log_kbn        => pl.log_kbn,
            :create_user_id => pl.create_user_id,
            :created_on     => pl.created_on
          }
        end
        item_list.concat items
      end
    end
    result = {
      :items => item_list
    }
    render :text => result_for_json(true, '', result)
  end



  ###########################################################
  # メソッド：json_init_project_logsアクション
  # 概　　要：dat_projectlogs情報をJSON形式で返す。
  #           Airアプリから呼び出される
  ###########################################################
  def json_init_tasks
    item_list = []
    projects = my_projects_for_includes()
    projects.each do | project |
      project.dat_projectcomps.each do |pc|
        if ! pc.dat_task.blank?
            item_list.push pc.dat_task.attributes
        end
      end
    end
    result = {
      :items => item_list
    }
    render :text => result_for_json(true, '', result)
  end



  ###########################################################
  # メソッド：json_init_taskusersアクション
  # 概　　要：dat_taskusers情報をJSON形式で返す。
  #           Airアプリから呼び出される
  ###########################################################
  def json_init_taskusers
    item_list = []
    u = @current_user
    opt = {
      :conditions => ["dat_projects.valid_flg = 1 AND dat_projects.id in (SELECT pu.project_id FROM dat_projectusers pu WHERE pu.user_id = ? ) ", u.id],
      :order      => "dat_taskusers.id asc",
      :include    => [{:dat_projectusers=>[:dat_taskusers, :mst_user]}]
    }
    projects = DatProject.find(:all, opt)
    projects.each do | project |
      project.dat_projectusers.each do | pu |
        items = pu.dat_taskusers.map do |tu|
          {
            :id             => tu.id,
            :task_id        => tu.task_id,
            :projectuser_id => tu.projectuser_id,
            :create_user_id => tu.create_user_id,
            :created_on     => tu.created_on
          }
        end
        item_list.concat items
      end
    end
    result = {:items => item_list}
    render :text => result_for_json( true, '', result )
  end


  ###########################################################
  # メソッド：json_init_milestonesアクション
# 概　　要：dat_milestones情報をJSON形式で返す。
  #           Airアプリから呼び出される
  ###########################################################
  def json_init_milestones
    item_list = []
    projects = my_projects_for_includes()
    projects.each do | project |
      project.dat_projectcomps.each do |pc|
        if ! pc.dat_milestone.blank?
            item_list.push pc.dat_milestone.attributes
        end
      end
    end
    result = {:items => item_list}
    render :text => result_for_json( true, '', result )
  end



  ###########################################################
  # メソッド：json_init_eventsアクション
  # 概　　要：dat_events情報をJSON形式で返す。
  #           Airアプリから呼び出される
  ###########################################################
  def json_init_events
    item_list = []
    projects = my_projects_for_includes()
    projects.each do | project |
      project.dat_projectcomps.each do |pc|
        if ! pc.dat_event.blank?
            item_list.push pc.dat_event.attributes
        end
      end
    end
    result = {:items => item_list}
    render :text => result_for_json( true, '', result )
  end



  ###########################################################
  # メソッド：json_init_eventusersアクション
  # 概　　要：dat_eventusers情報をJSON形式で返す。
  #           Airアプリから呼び出される
  ###########################################################
  def json_init_eventusers
    u = @current_user
    opt = {
      :conditions => ["dat_projects.valid_flg = 1 AND dat_projects.id in (SELECT pu.project_id FROM dat_projectusers pu WHERE pu.user_id = ? ) ", u.id],
      :order      => "dat_eventusers.id asc",
      :include    => [{:dat_projectusers => [:dat_eventusers, :mst_user]}]
    }
    projects = DatProject.find(:all, opt)
    item_list = []
    projects.each do | project |
      project.dat_projectusers.each do | pu |
        items = pu.dat_eventusers.map do |tu|
        {
          :id             => tu.id,
          :event_id       => tu.event_id,
          :projectuser_id => tu.projectuser_id,
          :entry_flg      => tu.entry_flg,
          :create_user_id => tu.create_user_id,
          :created_on     => tu.created_on
        }
        end
        item_list.concat items
      end
    end

    result = {:items => item_list}
    render :text => result_for_json(true, '', result)
  end




  ###########################################################
  # メソッド：json_init_messagesアクション
  # 概　　要：mst_messages情報をJSON形式で返す。
  #           Airアプリから呼び出される
  ###########################################################
  def json_init_messages
    eventusers = MstMessage.find(:all, :order=>"id")
    item_list = []
    eventusers.each do | eventuser |
      item_list.push(eventuser.attributes)
    end
    result = {:items => item_list}
    render :text => result_for_json(true, '', result)
  end



  #
  #=== Airアプリ同期用
  #
  #Airアプリケーションとデータの同期を行う．
  #
  def sync_task()
    case request.method
      when :post
        json = params[:json]
        data = json ? ActiveSupport::JSON.decode(json) : {}
        #logger.debug data.inspect
        dat_projectcomps = data['dat_projectcomps']
        dat_tasks        = data['dat_tasks']
        dat_task_users   = data['dat_taskusers']
        #logger.debug dat_task_users.inspect
        
        if dat_projectcomps
          DatProjectcomp.transaction do
            dat_projectcomps.each do |comp|
              comp_id  = comp['id']
              local_id = comp['local_id']
              _task = nil
              dat_tasks.each do |task|
                if comp_id && task['project_tree_id'] == comp_id
                  _task = task
                elsif local_id && task['project_tree_id'] == local_id
                  _task = task
                end
              end
              comp[:task] = _task
              sync_air_for_task(comp, dat_task_users)
            end
          end
        end
      else
        # do nothing
    end
    
    project_id = data['project_id']
    
    dat_projectcomps = DatProjectcomp.find(:all, {
      :conditions=>["project_id = ? and task_kbn = 1", project_id]
    })
    _dat_projectcomps = dat_projectcomps.map do |comp|
      _comp = comp.attributes
      #_comp['complete_date'] = comp.complete_date.strftime('Y/m/d')
      #_comp['start_date']    = comp.start_date.strftime('Y/m/d')
      #_comp['end_date']      = comp.end_date.strftime('Y/m/d')
      #_comp
    end
    dat_tasks = DatTask.find(:all, {
      :conditions => ["dat_projectcomps.project_id = ?", project_id],
      :include    => [:dat_projectcomp]
    })
    _dat_tasks = dat_tasks.map do |task|
      _task = task.attributes
      _task['complete_date'] = task.complete_date.strftime('%Y/%m/%d') if task.complete_date
      _task['start_date']    = task.start_date.strftime('%Y/%m/%d') if task.start_date
      _task['end_date']      = task.end_date.strftime('%Y/%m/%d') if task.end_date
      _task
    end
    dat_taskusers = DatTaskuser.find(:all, {
      :conditions => ["dat_projectcomps.project_id = ?", project_id],
      :include    => [{:dat_task => :dat_projectcomp}]
    })
    _dat_taskusers = dat_taskusers.map do |user|
      _user = user.attributes
    end
    
    
    r = {
      :dat_projectcomps => _dat_projectcomps,
      :dat_tasks        => _dat_tasks,
      :dat_taskusers    => _dat_taskusers,
    }
    logger.debug r.inspect
    render :text => result_for_json(true, '', r)
  end


  private

  def sync_air_for_task(dat_projectcomp, users)
    r = false
    # 登録済みオブジェクトを取得
    is_new = false
    if dat_projectcomp.id
      opt = {
        :conditions => [" dat_projectcomps.id = ? ", dat_projectcomp['id']],
        #:include    => [{:dat_task => [:dat_taskusers]}]
        :include    => [:dat_task]
      }
      projectcomp = DatProjectcomp.find(:first, opt)
      task        = projectcomp.dat_task
    else
      is_new = true
      projectcomp = DatProjectcomp.new
      task        = DatTask.new
    end
    task_param = dat_projectcomp[:task]
    
    updated_on = Time.parse(task_param['updated_on'])
    logger.debug updated_on
    if is_new or updated_on >= projectcomp.updated_on
      projectcomp.item_name      = dat_projectcomp['item_name']
      projectcomp.class_word1    = dat_projectcomp['class_word1']
      projectcomp.class_word2    = dat_projectcomp['class_word2']
      projectcomp.class_word3    = dat_projectcomp['class_word3']
      projectcomp.update_user_id = dat_projectcomp['update_user_id']
      projectcomp.last_operation_kbn = dat_projectcomp['last_operation_kbn']
      
      task.update_user_id = task_param['update_user_id']
      task.main_user_id   = task_param['main_user_id']
      task.client_user_id = task_param['client_user_id']
      task.memo           = task_param['memo']
      task.result         = task_param['result']
      task.tani_kbn       = task_param['tani_kbn']
      task.progress_kbn   = task_param['progress_kbn']
      task.progress_rate  = task_param['progress_rate']
      task.exp_power      = task_param['exp_power']
      task.plan_power     = task_param['plan_power']
      task.fcas_power     = task_param['fcas_power']
      task.priority_kbn   = task_param['priority_kbn']
      task.complete_date  = Date.parse(task_param['complete_date'])
      task.start_date     = Date.parse(task_param['start_date'])
      task.end_date       = Date.parse(task_param['end_date'])
      logger.debug task.inspect
#=begin
      task.dat_taskusers.clear  #一旦削除
      if users
        users.each do |user|
          if user['task_id'] == task['id']
            taskuser = task.dat_taskusers.build({:projectuser_id => user['projectuser_id'], :create_user_id => task_param['update_user_id']})
          end
        end
      end
#=end
      if projectcomp.save and task.save
        r = true
      end
    else
      r = true
    end
    return r
  end




  private

  def my_projects
    opt = {
      :conditions => ["dat_projectusers.user_id = ? AND valid_flg = ?", @current_user.id, 1],
      :include    => [:dat_projectusers]
    }
    DatProject.find(:all, opt)
  end

  def my_projects_for_includes
    u = @current_user
    opt = {
      :conditions => ["dat_projects.valid_flg = 1 AND dat_projects.id in (SELECT pu.project_id FROM dat_projectusers pu WHERE pu.user_id = ? ) ", u.id],
      :order      => "dat_projectcomps.line_no asc",
      :include    => [
        {:dat_projectusers => :mst_user},
        {:dat_projectcomps => [
          :dat_milestone,
          {:dat_task=>[{:dat_user_main=>:mst_user}, {:dat_user_client=>:mst_user}]},
          :dat_event,
          :mst_user_create
        ]}
      ]
    }
    DatProject.find(:all, opt)
  end

  def my_projects_users
    users = []
    projects = my_projects
    projects.each do |p|
      projectusers = p.dat_projectusers.find(:all, :include => :mst_user, :conditions => ["mst_users.valid_flg = ?", 1])
      users = users + projectusers
    end
    users
  end

  def user_authorize
    @is_logined = false
    case request.method
    when :post
      logger.debug params['login_id'].inspect
      @current_user = MstUser.find_by_login_id(params[:login_id])
      logger.debug @current_user.inspect
      if @current_user
        if @current_user.password == params[:password]
          @is_logined = true
        end
      end
    end
    unless @is_logined
      render :text => 'Permission Denied', :status => 401
    end
    @is_logined
  end
end
